package com.geek.chat.server.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.geek.chat.common.protobuf.ProtoMsg;
import com.geek.chat.common.server.config.AttributteKeys;
import com.geek.chat.common.session.Session;
import com.geek.chat.server.operation.Operation;
import com.geek.chat.server.operation.OperationContext;
import com.geek.chat.server.session.SessionMap;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class ChatServerHandler extends ChannelHandlerAdapter{
	private Logger logger = LoggerFactory.getLogger(ChatServerHandler.class);
	
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
	}
	
	/**
	 * onMessage的时候回调，当有消息成功被解码之后回调此方法
	 */
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
		//logger.info("msg:{}",msg.toString());
		if (msg != null && msg instanceof ProtoMsg.Message) {
			ProtoMsg.Message pkg = (ProtoMsg.Message) msg;
			if (getSession(ctx) != null) {
				//根据
				int headType = pkg.getHeader();
				//需要实现抽象的逻辑层的Handler处理
				Operation operation = OperationContext.getInstance().getOperation(headType);
				if(null != operation){
					operation.action(getSession(ctx), pkg);
				} else {
					logger.warn("Not found operation Id: {}" , pkg.getHeader());
				}
			}
		}
	}

	/**
	 * 发生异常的时候回调
	 */
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		logger.error("CHANNEL_EXCEPTION " + cause);
		Session session = ctx.attr(AttributteKeys.SESSION).get();
		session.close();
	}

	@Override
	public void channelActive(final ChannelHandlerContext ctx) {
		//logger.info("CHANNEL_ACTIVE " + ctx.channel().remoteAddress());
		Session session = new Session(ctx);
		session.setLastActiveTimeToNow();
		ctx.channel().attr(AttributteKeys.SESSION).set(session);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		//logger.info("CHANNEL_INACTIVE " + ctx.channel().remoteAddress());
		Session session = getSession(ctx);
		if (session.isValid()) {
			session.close();
			SessionMap.sharedInstance().removeSession(session.getSessionUniqueId());
		}
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		//logger.info("CHANNEL_READ_COMPLETED " + ctx.channel().remoteAddress());
	}

	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		//logger.info("CHANNEL_REGISTERED");
	}

	private Session getSession(ChannelHandlerContext ctx) {
		return ctx.channel().attr(AttributteKeys.SESSION).get();
	}
}
